package org.game.module.datingbo.trigger;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.xiaoleilu.hutool.date.DateUnit;
import com.xiaoleilu.hutool.date.DateUtil;
import org.cfg.DatingRuleCfg;
import org.cfg.cache.DatingRuleCfgCache;
import org.cfg.cache.DiscreteDataCfgCache;
import org.constant.DatingConstant;
import org.constant.DiscreteDataID;
import org.constant.DiscreteDataKey;
import org.game.constant.BuildingConstant;
import org.game.constant.CityConstant;
import org.game.constant.DatingTypeConstant;
import org.game.db.bean.*;
import org.game.db.cache.BuildingCache;
import org.game.db.cache.CityCache;
import org.game.db.cache.RoleCache;
import org.game.module.datingbo.DatingBO;
import org.game.module.datingbo.DatingType;
import org.game.msgBuilder.DatingMsgBuilder;
import org.game.protobuf.s2c.S2CShareMsg;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 打工约会触发器
 * Created by fxf on 2018-3-14.
 */
@DatingType(DatingTypeConstant.DATING_TYPE_WORK)
public class WorkDatingTrigger extends AbstractCityDatingTrigger {

    @Override
    public void triggerDating(Player player, Map<String, List<Integer>> timeFrame, Date now) {
        List<Integer> triggerTimeFrame = timeFrame.get(DatingConstant.TRIGGER_TIME);
        //当前时段是否已经触发过
        if (alreadyTrigger(player, triggerTimeFrame)) {
            return;
        }
        //是否还有空闲城市
        Set<Building> buildingSet = getUsableBuilding(player);
        if (buildingSet.size() == 0) {
            return;
        }
        //筛选乱入约会
        List<DatingRuleCfg> multiplayerDatingList = getMultiplayerDating(buildingSet);
        //未触发乱入约会，才会尝试触发单人约会
        if (!filtrateDating(player, multiplayerDatingList, timeFrame,now)) {
            //筛选单人约会
            List<DatingRuleCfg> singleRoleDatingList = getSingleRoleDating(buildingSet);
            filtrateDating(player, singleRoleDatingList, timeFrame,now);
        }
    }

    @Override
    public void refreshCityDating(Player player, List<CityDatingRecord> recordList, Date now) {
        int outDatingTime = ((Map<Integer, Integer>) DiscreteDataCfgCache.me().getData(DiscreteDataID.DATING, DiscreteDataKey.DATING_OUT_TIME)).get(DatingTypeConstant.DATING_TYPE_WORK);
        List<CityDatingRecord> outTimeRecordList = recordList.stream()
                .filter(record -> DateUtil.between(record.getCityDatingRecordProxy().getTriggerTime(), now, DateUnit.MINUTE) >= outDatingTime)
                .peek(record -> record.delete())
                .collect(Collectors.toList());
        if (outTimeRecordList != null && outTimeRecordList.size() > 0) {
            player.getPlayerProxy().sendMsg(DatingBO.updateCityDatingList, DatingMsgBuilder.buildCityDatingInfoList(S2CShareMsg.ChangeType.DELETE, outTimeRecordList));
        }
        refreshCity(player, outTimeRecordList);
    }


    /**
     * 获得可以进行打工约会的区域
     */
    private Set<Building> getUsableBuilding(Player player) {

        List<Integer> freeWorkCityList = CityCache.me().getCityCacheProxy().getFreeCityList(player, city -> city.getCityProxy().getCfg().getBuildType() == CityConstant.WORK_ZONE);

        Set<Building> buildingSet = Sets.newHashSet();


        freeWorkCityList.forEach(cityCid -> {
            City city = CityCache.me().getByCidPlayerId(cityCid, player.getId());
            List<Building> buildingList = BuildingCache.me().getBuildingCacheProxy().getBuildingListByCity(player, city.getCid());
            buildingList.forEach(building -> {
                if (building.getState() == BuildingConstant.BUIDING_STATE_WORK) {
                    buildingSet.add(building);
                }
            });
        });
        return buildingSet;
    }

    /**
     * 获取乱入约会
     *
     * @param buildingList 建筑列表
     */
    private List<DatingRuleCfg> getMultiplayerDating(Collection<Building> buildingList) {
        List<DatingRuleCfg> allDatingRuleCfg = DatingRuleCfgCache.me().getAll();
        List<DatingRuleCfg> result = Lists.newArrayList();
        buildingList.forEach(building -> {
            List<Integer> roleList = building.getBuildingProxy().getCanCityDatingRoleList();
            if (roleList.size() <= 1) {
                return;
            }
            //注：好感度临界值条件在getUsableCity方法里面已经处理，在临界值的role不加入workRole列表，所以此处无需进行判断
            List<DatingRuleCfg> list = allDatingRuleCfg.stream()
                    .filter(cfg -> cfg.getType() == DatingTypeConstant.DATING_TYPE_WORK)//筛选约会类型
                    .filter(cfg -> cfg.getEnterCondtionByType(DatingConstant.ENTER_CDTION_KEY_BUILD_CID) == building.getBuildingProxy().getBuildId())
                    .filter(cfg -> ((List) cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS)).size() > 1)
                    .filter(cfg -> roleList.containsAll((List) cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS)))
                    .collect(Collectors.toList());
            result.addAll(list);
        });
        return result;
    }

    /**
     * 获取单人打工约会
     */
    private List<DatingRuleCfg> getSingleRoleDating(Collection<Building> buildingList) {
        List<DatingRuleCfg> allDatingRuleCfg = DatingRuleCfgCache.me().getAll();
        List<DatingRuleCfg> result = Lists.newArrayList();
        buildingList.forEach(building -> {
            List<Integer> roleList = building.getBuildingProxy().getCanCityDatingRoleList();
            //注：好感度临界值条件在getUsableCity方法里面已经处理，在临界值的role不加入workRole列表，所以此处无需进行判断
            List<DatingRuleCfg> list = allDatingRuleCfg.stream()
                    .filter(cfg -> cfg.getType() == DatingTypeConstant.DATING_TYPE_WORK)
                    .filter(cfg -> cfg.getEnterCondtionByType(DatingConstant.ENTER_CDTION_KEY_BUILD_CID) == building.getBuildingProxy().getBuildId())
                    .filter(cfg -> ((List) cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS)).size() == 1)
                    .filter(cfg -> roleList.containsAll((Collection<?>) cfg.getEnterCondition().get(DatingConstant.ENTER_CDTION_KEY_ROLE_CIDS)))
                    .collect(Collectors.toList());
            result.addAll(list);
        });
        return result;
    }
}


